import os
import csv
import chardet
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QRadioButton,
                             QFileDialog, QComboBox, QListWidget, QGroupBox, QAbstractItemView,
                             QMessageBox, QLineEdit)
from PySide6.QtGui import QFont
from PySide6.QtCore import QSettings, Signal
from python_calamine import CalamineWorkbook
from utils.first_row_reader import FirstRowReader

class FileWidget(QWidget):
    """文件选择Tab组件"""

    csv_columns = Signal(list)
    next_clicked = Signal()  # 下一步

    def __init__(self, app_data, parent=None):
        super().__init__(parent)
        self.settings = QSettings('Mysoft', 'test')
        self.selected_files = app_data.selected_files
        self.app_data = app_data
        self.parent = parent
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout(self)

        # 标题
        title = QLabel("表格文件选择与合并")
        title.setFont(QFont("Arial", 16, QFont.Bold))
        layout.addWidget(title)

        # 文件类型选择
        btn_layout = QHBoxLayout()
        btn_layout.addWidget(QLabel("选择文件类型"))
        self.file_type_combo = QComboBox()
        self.file_type_combo.addItems(["CSV", "XLSX"])
        self.file_type_combo.currentTextChanged.connect(self.on_file_type_changed)
        btn_layout.addWidget(self.file_type_combo)
        layout.addLayout(btn_layout)
        
        # 文件选择区域
        self.file_group = QGroupBox("选择CSV文件")
        file_layout = QVBoxLayout(self.file_group)

        self.xlsx_sheet_widget = QWidget()  # 创建容器部件
        self.xlsx_sheet_layout = QHBoxLayout(self.xlsx_sheet_widget)  # 布局绑定到容器
        self.radio_last_sheet = QRadioButton("使用最后一个sheet")
        self.radio_specify_sheet = QRadioButton("指定sheet名称")
        self.sheet_name_edit = QLineEdit()
        self.sheet_name_edit.setPlaceholderText("输入sheet名称")
        self.sheet_name_edit.setEnabled(False)
        self.radio_last_sheet.setChecked(True)
        self.radio_specify_sheet.toggled.connect(self.toggle_sheet_name_edit)
        self.xlsx_sheet_layout.addWidget(self.radio_last_sheet)
        self.xlsx_sheet_layout.addWidget(self.radio_specify_sheet)
        self.xlsx_sheet_layout.addWidget(self.sheet_name_edit)
        self.xlsx_sheet_widget.setVisible(False)  # 初始隐藏容器
        file_layout.addWidget(self.xlsx_sheet_widget)  # 容器加入父布局

        # 文件列表
        self.file_list = QListWidget()
        self.file_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        file_layout.addWidget(self.file_list)

        # 按钮区域
        btn_layout = QHBoxLayout()
        add_btn = QPushButton("添加文件")
        add_btn.clicked.connect(self.add_files)
        btn_layout.addWidget(add_btn)

        remove_btn = QPushButton("移除选中")
        remove_btn.clicked.connect(self.remove_files)
        btn_layout.addWidget(remove_btn)

        clear_btn = QPushButton("清空列表")
        clear_btn.clicked.connect(self.clear_files)
        btn_layout.addWidget(clear_btn)

        file_layout.addLayout(btn_layout)
        layout.addWidget(self.file_group)

        # 下一步按钮
        next_btn = QPushButton("下一步：设备配置")
        next_btn.clicked.connect(self.on_next_clicked)
        layout.addWidget(next_btn)

    def on_file_type_changed(self, file_type):
        """文件类型切换时更新UI"""
        self.app_data.file_type = file_type
        if file_type == "XLSX":
            self.file_group.setTitle("请选择一个或多个XLSX文件")
        else:
            self.file_group.setTitle("请选择一个或多个CSV文件")

    def add_files(self):
        """添加文件"""
        last_dir = self.settings.value("last_file_directory", "", type=str)
        
        if self.app_data.file_type == "CSV":
            files, _ = QFileDialog.getOpenFileNames(
                self, "选择CSV文件", last_dir, "CSV文件 (*.csv);;所有文件 (*)"
            )
        else:
            files, _ = QFileDialog.getOpenFileNames(
                self, "选择XLSX文件", last_dir, "XLSX文件 (*.xlsx);;所有文件 (*)"
            )
        
        if files:
            # 避免重复添加
            new_files = [f for f in files if f not in self.selected_files]
            if new_files:
                self.selected_files.extend(new_files)
                self.file_list.addItems(new_files)
                self.settings.setValue("last_file_directory", os.path.dirname(files[0]))
                
                # 检查文件一致性
                if self.app_data.file_type == "CSV":
                    self.check_csv()
                else:
                    self.check_xlsx()

    def remove_files(self):
        """移除选中文件"""
        selected_items = self.file_list.selectedItems()
        if not selected_items:
            return

        for item in selected_items:
            file_path = item.text()
            if file_path in self.selected_files:
                self.selected_files.remove(file_path)
            self.file_list.takeItem(self.file_list.row(item))

    def clear_files(self):
        """清空文件列表"""
        self.selected_files.clear()
        self.file_list.clear()

    def check_csv(self):
        """检查CSV文件列名一致性"""
        if not self.selected_files:
            return True
            
        headers = []
        base_encoding = 'utf-8'
        
        for path in self.selected_files:
            try:
                # 检测文件编码
                with open(path, 'rb') as f:
                    raw = f.read(10000)
                    enc = chardet.detect(raw)['encoding']
                    encoding = enc or base_encoding

                # 读取第一行
                with open(path, 'r', encoding=encoding, errors='replace') as f:
                    reader = csv.reader(f)
                    first_row = next(reader, None)

                    if first_row is None:
                        headers.append([])
                        continue

                    headers.append([col.strip() for col in first_row])

            except Exception as e:
                QMessageBox.warning(self, "警告", f"处理文件 {path} 出错: {str(e)}")
                return False

        # 比较所有文件的列名
        reference = headers[0]
        for i, header in enumerate(headers[1:]):
            if header != reference:
                QMessageBox.warning(
                    self, "列名不一致", 
                    f"文件 {os.path.basename(self.selected_files[0])} 与 {os.path.basename(self.selected_files[i+1])} 的列名不一致"
                )
                return False
        self.csv_columns.emit(reference)
        QMessageBox.information(self, "提示", f"一致性检查通过，共 {len(self.selected_files)} 个CSV文件")

    def check_xlsx(self):
        """检查XLSX文件一致性，检查一下是否都具有输入的sheet名称"""
        headers = []
        sheet_name = self.sheet_name_edit.text()
        if not sheet_name:
            return
        if not self.selected_files:
            return 
        for path in self.selected_files:
            sheet_names = self.get_sheet_names(path)
            if sheet_name not in sheet_names:
                QMessageBox.warning(
                    self, "错误", 
                    f"文件 {path} 的所有工作表\n ({sheet_names}) \n 不包含指定工作表 ({sheet_name}) !"
                )
                return
            if not headers:
                util = FirstRowReader(path)
                headers = util.read_header_by_sheetname(sheet_name)
                self.csv_columns.emit(headers)
        QMessageBox.information(self, "提示", f"一致性检查通过，共 {len(self.selected_files)} 个XLSX文件")

    @property
    def sheet_name(self):
        if self.radio_specify_sheet.isChecked():
            sheet_name = self.sheet_name_edit.text()
        else:
            sheet_name = ""
        return sheet_name

    def get_sheet_names(self, path):
        """获取XLSX文件中最后一个工作表名称"""
        workbook = CalamineWorkbook.from_path(path)
        sheet_names = workbook.sheet_names
        return sheet_names

    def on_next_clicked(self):
        """下一步按钮点击事件，由主窗口处理切换Tab"""
        self.next_clicked.emit()

    def on_file_type_changed(self, file_type):
        """文件类型切换时，控制「容器部件」的显示"""
        self.app_data.file_type = file_type
        self.file_group.setTitle(f"请选择一个或多个{file_type}文件")
        # 显示/隐藏「容器部件」（而非布局）
        self.xlsx_sheet_widget.setVisible(file_type == "XLSX")

    def toggle_sheet_name_edit(self, checked):
        """切换sheet名称输入框的启用状态"""
        self.sheet_name_edit.setEnabled(checked)
        if not checked:
            self.sheet_name_edit.clear()